package lrscp.lib.CmdUtils.Service;

import lrscp.lib.Log;

public class OsCmd {
	static boolean DEBUG = false;
	
	public interface OnCmdFinishedListener {
		void OnCmdFinished(boolean sucess, String cmd, String stdout, String stderr);
	}
	
	/** execute immediately */
	public static boolean exec(String cmd){
		return exec(cmd, null, null, 0, null);
	}
	
	public static boolean exec(String cmd, long timeOut){
		return exec(cmd, new StringBuffer(), new StringBuffer(), timeOut, null);
	}
	
	/** if timeOut=0, the cmd will be sent and returned immediately */
	public static boolean exec(String cmd, StringBuffer stderr, StringBuffer stdout, long timeOut, OnCmdFinishedListener listener){
			boolean ret = true;
			StreamReadThread errThd = null;
			StreamReadThread stdThd = null;

			try {
				if(DEBUG) {
					Log.i("exec cmd:" + cmd);
				}
				Process exec = Runtime.getRuntime().exec(cmd);

				if(timeOut == 0){
					return true;
				}
				
				Object isRet = new Object();
				errThd = new StreamReadThread("stderr", exec.getErrorStream(), stderr, isRet);
				stdThd = new StreamReadThread("stdout", exec.getInputStream(), stdout, isRet);

				long lastTime = System.currentTimeMillis();
				synchronized (isRet) {
					stdThd.start();
					errThd.start();
					isRet.wait(timeOut);
				}

				if (System.currentTimeMillis() - lastTime >= (long) timeOut) {
					Log.e("exec cmd timeout!!! " + timeOut);
					exec.destroy();
					ret = false;
				} else {
					//Log.i("waiting for process exit code");
					ret = exec.waitFor() == 0;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}

			// kill threads
			if (errThd.isAlive()) {
				errThd.stop();
			}
			if (stdThd.isAlive()) {
				stdThd.stop();
			}
			if (DEBUG) {
				Log.i("stdout:" + stdout.toString());
				Log.i("stderr:" + stderr.toString());
			}
			if (listener != null) {
				listener.OnCmdFinished(ret, cmd, stdout.toString(), stderr.toString());
			}
			return ret;
	}
}
